1 /* 2 * Written by Doug Lea with assistance from members of JCP JSR-166 3 * Expert Group and released to the public domain, as explained at 4 * http://creativecommons.org/publicdomain/zero/1.0/ 5 */ 6 7 /* 8 * Source: 9 * http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/jsr166e/LongAdder.java?revision=1.17 10 */ 11 12 package com.google.common.cache; 13 14 import com.google.common.annotations.GwtCompatible; 15 16 import java.io.IOException; 17 import java.io.ObjectInputStream; 18 import java.io.ObjectOutputStream; 19 import java.io.Serializable; 20 import java.util.concurrent.atomic.AtomicLong; 21 22 /** 23 * One or more variables that together maintain an initially zero 24 * {@code long} sum. When updates (method {@link #add}) are contended 25 * across threads, the set of variables may grow dynamically to reduce 26 * contention. Method {@link #sum} (or, equivalently, {@link 27 * #longValue}) returns the current total combined across the 28 * variables maintaining the sum. 29 * 30 * <p>This class is usually preferable to {@link AtomicLong} when 31 * multiple threads update a common sum that is used for purposes such 32 * as collecting statistics, not for fine-grained synchronization 33 * control. Under low update contention, the two classes have similar 34 * characteristics. But under high contention, expected throughput of 35 * this class is significantly higher, at the expense of higher space 36 * consumption. 37 * 38 * <p>This class extends {@link Number}, but does <em>not</em> define 39 * methods such as {@code equals}, {@code hashCode} and {@code 40 * compareTo} because instances are expected to be mutated, and so are 41 * not useful as collection keys. 42 * 43 * <p><em>jsr166e note: This class is targeted to be placed in 44 * java.util.concurrent.atomic.</em> 45 * 46 * @since 1.8 47 * @author Doug Lea 48 */ 49 @GwtCompatible(emulated = true) 50 final class LongAdder extends Striped64 implements Serializable, LongAddable { 51 private static final long serialVersionUID = 7249069246863182397L; 52 53 /** 54 * Version of plus for use in retryUpdate 55 */ 56 final long fn(long v, long x) { return v + x; } 57 58 /** 59 * Creates a new adder with initial sum of zero. 60 */ 61 public LongAdder() { 62 } 63 64 /** 65 * Adds the given value. 66 * 67 * @param x the value to add 68 */ 69 public void add(long x) { 70 Cell[] as; long b, v; int[] hc; Cell a; int n; 71 if ((as = cells) != null || !casBase(b = base, b + x)) { 72 boolean uncontended = true; 73 if ((hc = threadHashCode.get()) == null || 74 as == null || (n = as.length) < 1 || 75 (a = as[(n - 1) & hc[0]]) == null || 76 !(uncontended = a.cas(v = a.value, v + x))) 77 retryUpdate(x, hc, uncontended); 78 } 79 } 80 81 /** 82 * Equivalent to {@code add(1)}. 83 */ 84 public void increment() { 85 add(1L); 86 } 87 88 /** 89 * Equivalent to {@code add(-1)}. 90 */ 91 public void decrement() { 92 add(-1L); 93 } 94 95 /** 96 * Returns the current sum. The returned value is <em>NOT</em> an 97 * atomic snapshot; invocation in the absence of concurrent 98 * updates returns an accurate result, but concurrent updates that 99 * occur while the sum is being calculated might not be 100 * incorporated. 101 * 102 * @return the sum 103 */ 104 public long sum() { 105 long sum = base; 106 Cell[] as = cells; 107 if (as != null) { 108 int n = as.length; 109 for (int i = 0; i < n; ++i) { 110 Cell a = as[i]; 111 if (a != null) 112 sum += a.value; 113 } 114 } 115 return sum; 116 } 117 118 /** 119 * Resets variables maintaining the sum to zero. This method may 120 * be a useful alternative to creating a new adder, but is only 121 * effective if there are no concurrent updates. Because this 122 * method is intrinsically racy, it should only be used when it is 123 * known that no threads are concurrently updating. 124 */ 125 public void reset() { 126 internalReset(0L); 127 } 128 129 /** 130 * Equivalent in effect to {@link #sum} followed by {@link 131 * #reset}. This method may apply for example during quiescent 132 * points between multithreaded computations. If there are 133 * updates concurrent with this method, the returned value is 134 * <em>not</em> guaranteed to be the final value occurring before 135 * the reset. 136 * 137 * @return the sum 138 */ 139 public long sumThenReset() { 140 long sum = base; 141 Cell[] as = cells; 142 base = 0L; 143 if (as != null) { 144 int n = as.length; 145 for (int i = 0; i < n; ++i) { 146 Cell a = as[i]; 147 if (a != null) { 148 sum += a.value; 149 a.value = 0L; 150 } 151 } 152 } 153 return sum; 154 } 155 156 /** 157 * Returns the String representation of the {@link #sum}. 158 * @return the String representation of the {@link #sum} 159 */ 160 public String toString() { 161 return Long.toString(sum()); 162 } 163 164 /** 165 * Equivalent to {@link #sum}. 166 * 167 * @return the sum 168 */ 169 public long longValue() { 170 return sum(); 171 } 172 173 /** 174 * Returns the {@link #sum} as an {@code int} after a narrowing 175 * primitive conversion. 176 */ 177 public int intValue() { 178 return (int)sum(); 179 } 180 181 /** 182 * Returns the {@link #sum} as a {@code float} 183 * after a widening primitive conversion. 184 */ 185 public float floatValue() { 186 return (float)sum(); 187 } 188 189 /** 190 * Returns the {@link #sum} as a {@code double} after a widening 191 * primitive conversion. 192 */ 193 public double doubleValue() { 194 return (double)sum(); 195 } 196 197 private void writeObject(ObjectOutputStream s) throws IOException { 198 s.defaultWriteObject(); 199 s.writeLong(sum()); 200 } 201 202 private void readObject(ObjectInputStream s) 203 throws IOException, ClassNotFoundException { 204 s.defaultReadObject(); 205 busy = 0; 206 cells = null; 207 base = s.readLong(); 208 } 209 210 }